/*
 * @Description: 外部网页   webview
 * @version: 
 * @Company: 
 * @Author: ZhengZhuang
 * @Date: 2019-09-02 14:20:47
 * @LastAuthor   : zhengzhuang
 * @lastTime     : 2019-12-23 11:35:22
 */
import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'package:C20Driver/utils/toast.dart';
import 'package:amap_location_fluttify/amap_location_fluttify.dart';
import 'package:flutter/material.dart';
import 'package:C20Driver/routers/navigator_util.dart';
import 'package:C20Driver/utils/locate_info.dart';
import 'package:C20Driver/utils/map_util.dart';
import 'package:C20Driver/widget/app_share.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:url_launcher/url_launcher.dart';
import 'package:webview_flutter/webview_flutter.dart';
import '../../resources/app_storage_interface.dart';

// const String kNavigationExamplePage = '''
// <!DOCTYPE html><html>
// <head><title>Navigation Delegate Example</title></head>
// <body>
// <p>
// The navigation delegate is set to block navigation to the jd website.
// </p>
// <ul>
// <ul><a href="https://www.jd.com/">https://www.jd.com/</a></ul>
// <ul><a href="https://www.baidu.com/">https://www.baidu.com/</a></ul>
// </ul>
// </body>
// </html>
// ''';

class WebAppView extends StatefulWidget {
  final String url;

  WebAppView(this.url);

  @override
  _WebAppViewState createState() => _WebAppViewState();
}

class _WebAppViewState extends State<WebAppView> {
  final Completer<WebViewController> _controller =
      Completer<WebViewController>();
  bool _webViewReady;
  WebViewController _webController;
  String _webTitle = '加载中...';
  String _token;

  @override
  void initState() {
    super.initState();
    if (Platform.isAndroid) WebView.platform = SurfaceAndroidWebView();
    _getToken();
  }

  void _getToken() async {
    SharedPreferences prefs = await SharedPreferences.getInstance();
    _token = prefs.getString(AppStorageInterface.LOGINTOKEN);
  }

  @override
  Widget build(BuildContext context) {
    return WillPopScope(
        child: Scaffold(
          appBar: AppBar(
            title: Text(_webTitle),
            elevation: 0.0,
            // This drop down menu demonstrates that Flutter widgets can be shown over the web view.
            actions: <Widget>[
              NavigationControls(_controller.future),
            ],
          ),
          // We're using a Builder here so we have a context that is below the Scaffold
          // to allow calling Scaffold.of(context) so we can show a snackbar.
          body: Container(
            child: Column(
              children: <Widget>[
                Expanded(
                    child: WebView(
                  initialUrl: widget.url,
                  javascriptMode: JavascriptMode.unrestricted,
                  onWebViewCreated:
                      (WebViewController webViewController) async {
                    _webController = webViewController;
                    _webController.clearCache();
                  },
                  javascriptChannels: <JavascriptChannel>[
                    _toasterJavascriptChannel(context),
                    _getAppToken(context),
                    _getCurrentLatlng(context),
                    _getLocationInfo(context),
                    _jumpRouter(context),
                    _wxShare(context),
                    _appPayment(context),
                    _openAmap(context),
                    _openBaiduMap(context),
                    _jumpWebViewRouter(context),
                    _pushInfo(context)
                  ].toSet(),
                  navigationDelegate: (NavigationRequest request) async {
                    if (Platform.isAndroid) {
                      if (request.url.contains("wx.tenpay.com")) {
                        _webController.loadUrl(request.url,
                            headers: {"referer": widget.url});
                        return NavigationDecision.prevent;
                      }
                    }

                    if (Platform.isIOS) {
                      if (request.url.startsWith('alipay://') ||
                          request.url.startsWith('weixin://wap/pay?')) {
                        await launch(request.url);
                        return NavigationDecision.prevent;
                      } else {
                        return NavigationDecision.navigate;
                      }
                    } else {
                      if (request.url.startsWith('alipays://') ||
                          request.url.startsWith('weixin://wap/pay?')) {
                        await launch(request.url);
                        return NavigationDecision.prevent;
                      } else {
                        return NavigationDecision.navigate;
                      }
                    }
                  },
                  onPageStarted: (String url) async {
                    print("onPageStarted---------------1");
                    print("webview设置token11111");
                  },
                  onPageFinished: (String url) async {
                    print("onPageFinished---------------2" + url);
                    // _webController.loadUrl(request.url, headers: {
                    //   'referer': request.url,
                    // });
                    /// webview设置token
                    SharedPreferences prefs =
                        await SharedPreferences.getInstance();
                    _webController
                        .evaluateJavascript(
                            "(function() { try { window.localStorage.setItem('token', '${prefs.getString(AppStorageInterface.LOGINTOKEN)}');return window.localStorage.authToken; } catch (err) { return err; } })();")
                        .then((result) {});

                    /// 设置title
                    String _dataInfo = await _webController.getTitle();
                    if (mounted) {
                      setState(() {
                        _webTitle = _dataInfo;
                      });
                    }
                  },
                  gestureNavigationEnabled: true,
                ))
              ],
            ),
          ),
          // floatingActionButton: favoriteButton(),
        ),
        onWillPop: () async {
          if (await _webController.canGoBack()) {
            await _webController.goBack();
            return false;
          } else {
            NavigatorUtil.goBack(context);
            return true;
          }
        });
  }

  JavascriptChannel _toasterJavascriptChannel(BuildContext context) {
    return JavascriptChannel(
        name: 'Toaster',
        onMessageReceived: (JavascriptMessage message) {
          Scaffold.of(context).showSnackBar(
            SnackBar(content: Text(message.message)),
          );
        });
  }

  /// 获取当前token
  /// js调用：getCurrentLatlng.postMessage('传递的数据');
  JavascriptChannel _getAppToken(BuildContext context) {
    return JavascriptChannel(
        name: 'getAppToken',
        onMessageReceived: (JavascriptMessage message) async {
          SharedPreferences prefs = await SharedPreferences.getInstance();
          String _token =
              prefs.getString(AppStorageInterface.LOGINTOKEN); // 存储token到本地
          _webController.evaluateJavascript('getAppToken("$_token")');
        });
  }



  /// 通过经纬度查询当前位置
  JavascriptChannel _getLocationInfo(BuildContext context) {
    return JavascriptChannel(
        name: 'getLocationInfo',
        onMessageReceived: (JavascriptMessage message) async {
          LatLng _locationInfo = LatLng.fromJson(jsonDecode(message.message));
          LocateInfo().getLocationInfo(_locationInfo).then((value) =>
              _webController.evaluateJavascript('getLocationInfo("$value")'));
        });
  }

  /// 路由跳转
  JavascriptChannel _jumpRouter(BuildContext context) {
    return JavascriptChannel(
        name: 'jumpRouter',
        onMessageReceived: (JavascriptMessage message) async {
          NavigatorUtil.jump(context, message.message);
        });
  }

  /// webview路由跳转
  JavascriptChannel _jumpWebViewRouter(BuildContext context) {
    return JavascriptChannel(
        name: 'jumpWebViewRouter',
        onMessageReceived: (JavascriptMessage message) async {
          NavigatorUtil.jumpWebView(context, message.message).then((value) {
            _webController?.evaluateJavascript(
                "(function() { try { window.localStorage.setItem('token', '$_token');return window.localStorage.authToken; } catch (err) { return err; } })();");
          });
        });
  }

  /// 微信分享
  JavascriptChannel _wxShare(BuildContext context) {
    return JavascriptChannel(
        name: 'wxShare',
        onMessageReceived: (JavascriptMessage message) async {
          // AppShare().webviewWxMiniprogramShare(context, "0040", message.message);
        });
  }

  /// App支付
  JavascriptChannel _appPayment(BuildContext context) {
    return JavascriptChannel(
        name: 'appPayment',
        onMessageReceived: (JavascriptMessage message) {
          // AppPaymentWidget.webviewShow(context, _webController, message.message);
        });
  }

  /// 打开高德地图导航
  JavascriptChannel _openAmap(BuildContext context) {
    return JavascriptChannel(
        name: 'openAmap',
        onMessageReceived: (JavascriptMessage message) {
          LatLng _locationInfo = LatLng.fromJson(jsonDecode(message.message));
          MapUtil.gotoAMap(_locationInfo.longitude, _locationInfo.latitude);
        });
  }

  /// 打开百度地图导航
  JavascriptChannel _openBaiduMap(BuildContext context) {
    return JavascriptChannel(
        name: 'openBaiduMap',
        onMessageReceived: (JavascriptMessage message) {
          LatLng _locationInfo = LatLng.fromJson(jsonDecode(message.message));
          MapUtil.gotoBaiduMap(_locationInfo.longitude, _locationInfo.latitude);
        });
  }
  /// 获取当前经纬度
  /// js调用：getCurrentLatlng.postMessage('传递的数据');
  JavascriptChannel _getCurrentLatlng(BuildContext context) {
    return JavascriptChannel(
        name: 'getCurrentLatlng',
        onMessageReceived: (JavascriptMessage message) async {
          Location _dataInfo = await LocateInfo.getLocation(context);
          List latLng = [_dataInfo.latLng.latitude, _dataInfo.latLng.longitude];
          _webController
              .evaluateJavascript('getCurrentLatlng("${latLng.toString()}")');
        });
  }
  /// 传递信息
  JavascriptChannel _pushInfo(BuildContext context) {
    return JavascriptChannel(
        name: 'pushInfo',
        onMessageReceived: (JavascriptMessage message) {
          // ToastX.center("pushInfo");
          var mobile=18561784507;
          _webController.evaluateJavascript('pushInfoToJs("$mobile")') .then((value) => print("eeeeeeee"+value));
        });
  }

  Widget favoriteButton() {
    return FutureBuilder<WebViewController>(
        future: _controller.future,
        builder: (BuildContext context,
            AsyncSnapshot<WebViewController> controller) {
          if (controller.hasData) {
            return FloatingActionButton(
              onPressed: () async {
                final String url = await controller.data.currentUrl();
                Scaffold.of(context).showSnackBar(
                  SnackBar(content: Text('Favorited $url')),
                );
              },
              child: const Icon(Icons.favorite),
            );
          }
          return Container();
        });
  }
}

enum MenuOptions {
  showUserAgent,
  listCookies,
  clearCookies,
  addToCache,
  listCache,
  clearCache,
  navigationDelegate,
}

class SampleMenu extends StatelessWidget {
  SampleMenu(this.controller);

  final Future<WebViewController> controller;
  final CookieManager cookieManager = CookieManager();

  @override
  Widget build(BuildContext context) {
    return FutureBuilder<WebViewController>(
      future: controller,
      builder:
          (BuildContext context, AsyncSnapshot<WebViewController> controller) {
        return PopupMenuButton<MenuOptions>(
          onSelected: (MenuOptions value) {
            switch (value) {
              case MenuOptions.showUserAgent:
                _onShowUserAgent(controller.data, context);
                break;
              case MenuOptions.listCookies:
                _onListCookies(controller.data, context);
                break;
              case MenuOptions.clearCookies:
                _onClearCookies(context);
                break;
              case MenuOptions.addToCache:
                _onAddToCache(controller.data, context);
                break;
              case MenuOptions.listCache:
                _onListCache(controller.data, context);
                break;
              case MenuOptions.clearCache:
                _onClearCache(controller.data, context);
                break;
              case MenuOptions.navigationDelegate:
                // _onNavigationDelegateExample(controller.data, context);
                break;
            }
          },
          itemBuilder: (BuildContext context) => <PopupMenuItem<MenuOptions>>[
            PopupMenuItem<MenuOptions>(
              value: MenuOptions.showUserAgent,
              child: const Text('显示用户代理'),
              enabled: controller.hasData,
            ),
            const PopupMenuItem<MenuOptions>(
              value: MenuOptions.listCookies,
              child: Text('列出Cookie'),
            ),
            const PopupMenuItem<MenuOptions>(
              value: MenuOptions.clearCookies,
              child: Text('清楚cookies'),
            ),
            const PopupMenuItem<MenuOptions>(
              value: MenuOptions.addToCache,
              child: Text('添加到缓存'),
            ),
            const PopupMenuItem<MenuOptions>(
              value: MenuOptions.listCache,
              child: Text('列表缓存'),
            ),
            const PopupMenuItem<MenuOptions>(
              value: MenuOptions.clearCache,
              child: Text('清除缓存'),
            ),
            const PopupMenuItem<MenuOptions>(
              value: MenuOptions.navigationDelegate,
              child: Text('导航代理示例'),
            ),
          ],
        );
      },
    );
  }

  void _onShowUserAgent(
      WebViewController controller, BuildContext context) async {
    // Send a message with the user agent string to the Toaster JavaScript channel we registered
    // with the WebView.
    await controller.evaluateJavascript(
        'Toaster.postMessage("User Agent: " + navigator.userAgent);');
  }

  void _onListCookies(
      WebViewController controller, BuildContext context) async {
    final String cookies =
        await controller.evaluateJavascript('document.cookie');
    Scaffold.of(context).showSnackBar(SnackBar(
      content: Column(
        mainAxisAlignment: MainAxisAlignment.end,
        mainAxisSize: MainAxisSize.min,
        children: <Widget>[
          const Text('Cookies:'),
          _getCookieList(cookies),
        ],
      ),
    ));
  }

  void _onAddToCache(WebViewController controller, BuildContext context) async {
    await controller.evaluateJavascript(
        'caches.open("test_caches_entry"); localStorage["test_localStorage"] = "dummy_entry";');
    Scaffold.of(context).showSnackBar(const SnackBar(
      content: Text('Added a test entry to cache.'),
    ));
  }

  void _onListCache(WebViewController controller, BuildContext context) async {
    await controller.evaluateJavascript('caches.keys()'
        '.then((cacheKeys) => JSON.stringify({"cacheKeys" : cacheKeys, "localStorage" : localStorage}))'
        '.then((caches) => Toaster.postMessage(caches))');
  }

  void _onClearCache(WebViewController controller, BuildContext context) async {
    await controller.clearCache();
    Scaffold.of(context).showSnackBar(const SnackBar(
      content: Text("Cache cleared."),
    ));
  }

  void _onClearCookies(BuildContext context) async {
    final bool hadCookies = await cookieManager.clearCookies();
    String message = 'There were cookies. Now, they are gone!';
    if (!hadCookies) {
      message = 'There are no cookies.';
    }
    Scaffold.of(context).showSnackBar(SnackBar(
      content: Text(message),
    ));
  }

  // void _onNavigationDelegateExample(
  //     WebViewController controller, BuildContext context) async {
  //   final String contentBase64 = base64Encode(const Utf8Encoder().convert(kNavigationExamplePage));
  //   await controller.loadUrl('data:text/html;base64,$contentBase64');
  // }

  Widget _getCookieList(String cookies) {
    if (cookies == null || cookies == '""') {
      return Container();
    }
    final List<String> cookieList = cookies.split(';');
    final Iterable<Text> cookieWidgets =
        cookieList.map((String cookie) => Text(cookie));
    return Column(
      mainAxisAlignment: MainAxisAlignment.end,
      mainAxisSize: MainAxisSize.min,
      children: cookieWidgets.toList(),
    );
  }
}

class NavigationControls extends StatelessWidget {
  const NavigationControls(this._webViewControllerFuture)
      : assert(_webViewControllerFuture != null);
  final Future<WebViewController> _webViewControllerFuture;

  @override
  Widget build(BuildContext context) {
    return FutureBuilder<WebViewController>(
      future: _webViewControllerFuture,
      builder:
          (BuildContext context, AsyncSnapshot<WebViewController> snapshot) {
        final bool webViewReady =
            snapshot.connectionState == ConnectionState.done;
        // final WebViewController controller = snapshot.data;
        return Row(
          children: <Widget>[
            // IconButton(
            //   icon: const Icon(Icons.arrow_back_ios),
            //   onPressed: !webViewReady
            //       ? null
            //       : () async {
            //           print('当前=============');
            //           print(await controller.canGoBack());
            //           if (await controller.canGoBack()) {
            //             await controller.goBack();
            //           } else {
            //             Scaffold.of(context).showSnackBar(
            //               const SnackBar(content: Text("No back history item")),
            //             );
            //             NavigatorUtil.goBack(context);
            //             return;
            //           }
            //         },
            // ),
            // IconButton(
            //   icon: const Icon(Icons.arrow_forward_ios),
            //   onPressed: !webViewReady
            //       ? null
            //       : () async {
            //           if (await controller.canGoForward()) {
            //             await controller.goForward();
            //           } else {
            //             Scaffold.of(context).showSnackBar(
            //               const SnackBar(
            //                   content: Text("No forward history item")),
            //             );
            //             return;
            //           }
            //         },
            // ),
            IconButton(
              icon: const Icon(Icons.close, color: Colors.white),
              onPressed: () => NavigatorUtil.goBack(context),
            ),
            // IconButton(
            //   icon: const Icon(Icons.replay),
            //   onPressed: !webViewReady
            //       ? null
            //       : () {
            //           controller.reload();
            //         },
            // ),
          ],
        );
      },
    );
  }
}
